{# Logs (overseer_logs): one page's Logs section, or Overseer > Logs over every service (``logs_services`` to tick, ``logs_links`` for each line's page). The window's lines, newest first unless the order says otherwise, the filters that chose them, and new lines added over SSE at the newest end while it is open, unless paused (a paused line is dropped). Oldest first, the column-reverse scroller keeps that end in view as lines arrive. Above them, the window's volume (``logs.volume``): a bar per slice, stacked by tone, that narrows the lines to its time; a drag across bars narrows to all of them, and the bars behind the lines on screen are marked as the list scrolls (``data-range``, ``data-range-of`` in app.js). #} {% from "components/macros/form.html" import action, checklist, filter_input, range_chips, select %} {% set newest_first = logs_order == "desc" %}
{{ range_chips(logs_windows, logs_window, field="window", aria="Log window") }} {% if logs_services is defined %}{{ checklist("logs-services", "service", "Services", logs_services) }}{% endif %} {% if logs_containers %}{{ checklist("logs-containers", "container", "Containers", logs_containers) }}{% endif %} {{ checklist("logs-levels", "level", "Levels", logs_levels) }} {{ select("order", logs_orders, logs_order, blank=None) }} {{ filter_input("#logs-lines", "q", logs_q, placeholder="Search lines") }} {% if not logs.note %}
{{ action("Wrap", "data-wrap x-on:click=\"wrap = !wrap\" x-bind:aria-pressed=\"wrap\"") }} {{ action("Pause", "data-pause x-on:click=\"paused = !paused\" x-text=\"paused ? 'Resume' : 'Pause'\" x-bind:aria-pressed=\"paused\"") }} {% if logs.lines %} {{ action("Top", 'data-scroll-to="#logs-lines > tr:first-child"') }} {{ action("Bottom", 'data-scroll-to="#logs-lines > tr:last-child"') }} {% endif %}
{% endif %}
{% if logs.note %}

{{ logs.note }}

{% else %} {% if logs.volume %} {% set peak = [1] + logs.volume|map(attribute="total")|list %}{% set peak = peak|max %} {% set picked = request.query_params.get("from") %}
{% for bar in logs.volume %} {% set url = request.url.include_query_params(**{"from": bar.from, "to": bar.to}) %} {% for tone in logs_volume_tones if bar[tone] %}{% endfor %} {% endfor %}
{{ logs.volume[0].at }}now
{% if picked %}{% set every = request.url.remove_query_params(["from", "to"]) %}Whole window{% endif %}
{% endif %} {# Runs to the bottom of the window and scrolls inside, so the filters above stay put. A stream, so flat on the canvas, not on a card. #}
{# Fixed columns: lines a search shows again never re-measure the table. #} {% with rows = logs.lines, tones = logs_tones, links = logs_links if logs_links is defined else none %}{% include "pages/overseer/_logs_rows.html" %}{% endwith %}
{% if not logs.lines %}

No lines in this window yet; new ones appear as they are written.

{% endif %} {% endif %}